/*
 * Graph.cpp
 *
 *  Created on: Apr 1, 2014
 *      Author: zby
 */
#include "Graph.h"

using namespace graph;
//--------------------------------------------------------------------------------
unsigned int const Graph::EdgeInit=UINT_MAX; //means not connected
int const Graph::NodeValueInit=INT_MIN;
//--------------------------------------------------------------------------------

/*
* @brief    Constructor for graph. Node its connected with itself
* @param    size of graph
* @retval    none
*/
Graph::Graph(Node size): size(size){

    ppEdgeMatrix=NULL;
    pNodeValue=NULL;

    if(0==size) throw "Invalid parameter - size can't be 0";

    ppEdgeMatrix = new EdgeVal *[size];
    for(Node i=0; i<size; i++)
        ppEdgeMatrix[i]= new EdgeVal[size];
    pNodeValue = new NodeVal[size];

    for(Node i=0; i<size; i++)
    {
        pNodeValue[i]=NodeValueInit;
        for(Node j=0; j<size; j++)
            if(i==j) ppEdgeMatrix[i][j]=0;
            else     ppEdgeMatrix[i][j]=EdgeInit;
    }
    Ed=0;
}

/*
* @brief    Copy constructor for graph.
* @param    graph to be copy
* @retval    none
*/
Graph::Graph(const Graph &_g){

    ppEdgeMatrix=NULL;
    pNodeValue=NULL;
    this->size = _g.size;
    this->Ed = _g.Ed;

    ppEdgeMatrix = new EdgeVal *[size];
    for(Node i=0; i<size; i++)
        ppEdgeMatrix[i]= new EdgeVal[size];
    pNodeValue = new NodeVal[size];

    for(Node i=0; i<size; i++)
    {
        pNodeValue[i] = _g.pNodeValue[i];
        for(Node j=0; j<size; j++)
            if(i==j) ppEdgeMatrix[i][j]=_g.ppEdgeMatrix[i][j];
            else     ppEdgeMatrix[i][j]=_g.ppEdgeMatrix[i][j];
    }
}

/*
* @brief    Delete
* @param    none
* @retval    none
*/
Graph::~Graph(){
    //delete node table
    if(pNodeValue!=NULL)
        delete [] pNodeValue;
    pNodeValue=NULL;

    //delete connection table
    if(ppEdgeMatrix!=NULL)
    {
        for(Node i=0; i<size; i++)
            delete [] ppEdgeMatrix[i];
    }
    //!!!!!!tutaj usunac jeszcze to co powstało przy: ppEdgeMatrix = new EdgeVal *[size];
    ppEdgeMatrix=NULL;
    Ed=0;
}

/*
* @brief    Add new edge only if doesn't exist. Increment nr of edges
* @param    x - location of node
* @param    y - location of node
* @retval    true-added successfully; false-failure
*/
bool Graph:: AddEdge(Node x, Node y, EdgeVal a){
    // Argument validation.
    if((x>=size) || (y>=size) || (x==y)) return false;
    // See if the edge already exists.
    if(ppEdgeMatrix[x][y]!=EdgeInit) return false;

    ppEdgeMatrix[x][y]=a;
    ppEdgeMatrix[y][x]=a;
    Ed++;
    return true;
}

/*
* @brief    Delete edge only if exists. Decrement nr of edges
* @param    x - location of node
* @param    y - location of node
* @retval    true-deleted successfully; false-failure
*/
bool Graph:: DeleteEdge(Node x, Node y){
    // Argument validation.
    if((x>=size) || (y>=size) || (x==y)) return false;
    // See if the edge  exists.
    if(ppEdgeMatrix[x][y]==EdgeInit) return false;

    ppEdgeMatrix[x][y]=EdgeInit;
    ppEdgeMatrix[y][x]=EdgeInit;
    Ed--;
    return true;
}

/*
* @brief    Tests whether there is an edge from node x to node y.
* @param    x - location of node
* @param    y - location of node
* @retval    true-there's connection; false-theren's connection
*/
bool Graph:: Adjacent(Node x, Node y){
    // Argument validation.
    if((x>=size) || (y>=size)) return false;
    // See if the edge  exists.
    if(ppEdgeMatrix[x][y]!=EdgeInit) return true;
    else return false;
}

/*
* @brief    Return actual edge number.
* @param    none
* @retval    Amount of actual edge
*/
unsigned int Graph::E(void){return Ed;}

/*
* @brief    Return lists k node such that there is an edge from k to kx.
* @param    node
* @retval    vector list of connection
*/
vector<Node> Graph::Neighbors(Node k){

    vector<Node> vlist;
    //browse thru each nodes to check connections
    for(Node i=0; i<size; i++){
        if(i==k) continue;
        else if(ppEdgeMatrix[k][i]!=EdgeInit) vlist.push_back(i);
    }
    return vlist;
}

/*
* @brief    Return nodes' value.
* @param    node
* @retval    nodes' value or
*/
NodeVal Graph::Get_node_value(Node k){
    return pNodeValue[k];
}

/*
* @brief    Set nodes' value.
* @param    node
* @param    value to node be set
* @retval    none
*/
void Graph::Set_node_value(Node k, NodeVal a){
    // Argument validation.
    if(k<size) pNodeValue[k]=a;
}

/*
* @brief    Get edge between node x and node y.
* @param    x- node
* @param    y- node
* @retval    none
*/
EdgeVal Graph::Get_edge_value(Node x, Node y){
    return ppEdgeMatrix[x][y];
}

/*
* @brief    Set edge between node x and node y.
* @param    x- node
* @param    y- node
* * @param    a- EdgeVal
* @retval    true- set successfully, false - fail
*/
bool Graph::Set_edge_value(Node x, Node y, EdgeVal a){
    // Argument validation.
    if((x>=size) || (y>=size)) return false;
    else {
        ppEdgeMatrix[x][y]=a;
        ppEdgeMatrix[y][x]=a;
    }
    return true;
}

